//
//  PropertyWarpper.swift
//  333333333
//
//  Created by wangyong的MAC on 2021/9/7.
//

import Foundation
@propertyWrapper final class Flag<Value> {
    var wrappedValue: Value
    let name: String

    fileprivate init(wrappedValue: Value, name: String) {
        self.wrappedValue = wrappedValue
        self.name = name
    }
    var projectedValue: Flag { self }
}
struct FeatureFlags{
    @Flag(name: "feature-search")
    var isSearchEnabled = false

    @Flag(name: "experiment-note-limit")
    var maximumNumberOfNotes = 999
}
// 定义keys
private struct FlagCodingKey: CodingKey {
    var stringValue: String
    var intValue: Int?

    init(name: String) {
        stringValue = name
    }
    // 下面的初始化器是CodingKey协议必须实现的
    init?(stringValue: String) {
        self.stringValue = stringValue
    }
    init?(intValue: Int) {
        self.intValue = intValue
        self.stringValue = String(intValue)
    }
}
private protocol DecodableFlag {
    typealias Container = KeyedDecodingContainer<FlagCodingKey>
    func decodeValue(from container: Container) throws
}
extension FeatureFlags: Decodable {
  // 这个初始化方法之前是编译器默认生成的
    init(from decoder: Decoder) throws {
      // container它本质上是一个特殊的字典，只允许你访问具有特定键的值，把key放进这个dic中
        let container = try decoder.container(keyedBy: FlagCodingKey.self)
     // Mirror可以映射一个对象,方便观察这个对象的属性和值
        for child in Mirror(reflecting: self).children {
            // child.value是映像对象的属性值
            guard let flag = child.value as? DecodableFlag else {
                continue
            }
            try flag.decodeValue(from: container)
        }
    }
}
extension Flag: DecodableFlag where Value: Decodable {
    fileprivate func decodeValue(from container: Container) throws {
        // 注入key值
        let key = FlagCodingKey(name: name)
        if let value = try container.decodeIfPresent(Value.self, forKey: key) {
            wrappedValue = value
        }
    }
}
